package computation;

import util.GeoVertex;

public class Statistics
{
	// computes the average surface height
	// TODO: allow computation within a range query window
	public static double computeAverageSurfaceHeight(GeoVertex[] vertices)
	{
		double ret = 0.0;
		for(GeoVertex gv: vertices) ret += gv.z();
		ret /= vertices.length;
		return ret;
	}
	
	// computes the RMS height
	// TODO: allow computation within a range query window
	public static double computeRMSSurfaceHeight(GeoVertex[] vertices)
	{
		double ret = 0.0;
		for(GeoVertex gv: vertices) ret += (gv.z() * gv.z());
		ret /= vertices.length;
		return Math.sqrt(ret);
	}
	
	public static double computeTenpointHeight(GeoVertex[] vertices)
	{
		double ret = 0.0;
		
		double[] highest = new double[5];
		double[] lowest = new double[5];
		
		// init highest and lowest to be their opposite
		for (int i = 0; i < 5; i++)
		{
			highest[i] = Double.MIN_VALUE;
			lowest[i] = Double.MAX_VALUE;
		}
		
		// find the highest and lowest
		for(GeoVertex gv: vertices)
		{
			double value = gv.z();
			
			for (int i = 0; i < 5; i++)
			{
				if (highest[i] < value) highest[i] = value;
				if (lowest[i] > value) lowest[i] = value;
			}
		}
		
		// compute ten-point height
		for (int i = 0; i < 5; i++)
		{
			ret += highest[i];
			ret += lowest[i];
		}

		return ret / 5.0;
	}
	
	// while one can use computeRMSSurfaceHeight() this means that this function would require two loops as we still need the h^3 value
	public static double computeSkewness(GeoVertex[] vertices)
	{
		double Rq = 0.0;
		double H = 0.0;
		int size = vertices.length;
		
		for(GeoVertex gv: vertices) 
		{
			double value = gv.z();
			H += (value*value*value);
			Rq += (value * value);
		}
		
		Rq /= size;
		Rq = Math.sqrt(Rq);
		Rq = Rq*Rq*Rq;
		
		return (1.0/(size*Rq))*H;
	}

	
	// while one can use computeRMSSurfaceHeight() this means that this function would require two loops as we still need the h^4 value
	public static double computeKurtosis(GeoVertex[] vertices)
	{
		double Rq = 0.0;
		double H = 0.0;
		int size = vertices.length;
		
		for(GeoVertex gv: vertices) 
		{
			double value = gv.z();
			H += (value*value*value*value);
			Rq += (value * value);
		}
		
		Rq /= size;
		Rq = Math.sqrt(Rq);
		Rq = Rq*Rq*Rq*Rq;
		
		return (1.0/(size*Rq))*H;
	}
	
}
